package com.dashu.school.service;

import com.dashu.base.enums.ReplRyCode;
import com.dashu.base.enums.school.RelationshipType;
import com.dashu.base.utils.CopyUtil;
import com.dashu.base.utils.UIDUtil;
import com.dashu.base.utils.VerificationUtil;
import com.dashu.school.dto.RelationshipDTO;
import com.dashu.school.dto.RelationshipListDTO;
import com.dashu.school.dto.company.CompanyClsDTO;
import com.dashu.school.dto.company.CompanyDTO;
import com.dashu.school.dto.company.CompanyDepartmentDTO;
import com.dashu.school.handler.VerificationException;
import com.dashu.school.model.CompanyPersonal;
import com.dashu.school.model.QRelationship;
import com.dashu.school.model.Relationship;
import com.dashu.school.result.PageEnty;
import com.dashu.school.vo.RelationshipListVO;
import com.dashu.school.vo.RelationshipVO;
import com.google.common.collect.Lists;
import com.querydsl.core.BooleanBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.persistence.FlushModeType;
import javax.transaction.Transactional;
import java.util.List;

@Slf4j
@Service
public class RelationshipService extends DataService {
    @Autowired
    private CompanyService companyService;
    @Autowired
    private CompanyPersonalService companyPersonalService;
    @Autowired
    private CompanyClsService companyClsService;
    @Autowired
    private CompanyDepartmentService companyDepartmentService;

    @Transactional
    public RelationshipDTO add(RelationshipVO relationshipVO) {
        Relationship relationship = CopyUtil.copyEnty(relationshipVO, Relationship.class);
        try {
            long userId = Long.parseLong(VerificationUtil.getUserId());
            relationship.setId(UIDUtil.nextId());
            relationship.setCreateUser(userId);
            relationship.setCreateTime(System.currentTimeMillis());
            relationship.setBindMain(relationshipVO.getParentId());
            if (relationshipCount(relationshipVO.getParentId(), 0) > 4)
                throw new VerificationException(ReplRyCode.BIND_PARENT_FULL, ReplRyCode.BIND_PARENT_FULL.getMessage());
            if (relationshipCount(0, relationshipVO.getParentId()) > 4)
                throw new VerificationException(ReplRyCode.BIND_PERSONAL_FULL, ReplRyCode.BIND_PERSONAL_FULL.getMessage());
            CompanyPersonal companyPersonal = companyPersonalService.findByRelationship(relationshipVO.getClsId(), relationshipVO.getPersonalName(), relationshipVO.getNum());
            if (relationshipVO.getCompanyId() == companyPersonal.getCompanyId())
                throw new VerificationException(ReplRyCode.BIND_PARENT_PERSONAL, ReplRyCode.BIND_PARENT_PERSONAL.getMessage());
            Relationship relationship1 = existRelationship(relationshipVO.getParentId(), companyPersonal.getId());
            if (relationship1 != null)
                throw new VerificationException(ReplRyCode.EXIST_RELATIONSHIP, ReplRyCode.EXIST_RELATIONSHIP.getMessage());
            relationship.setBindSon(companyPersonal.getId());
            relationship.setRelationship(RelationshipType.map.get(relationshipVO.getRelationship()));
            entityManager.persist(relationship);
//            entityManager.flush();
            entityManager.setFlushMode(FlushModeType.AUTO);
        } catch (Exception e) {
            e.printStackTrace();
            throw new VerificationException(ReplRyCode.DATA_NOT_INVALID, ReplRyCode.DATA_NOT_INVALID.getMessage());
        }
        RelationshipDTO relationshipDTO = CopyUtil.copyEnty(relationship, RelationshipDTO.class);
        return relationshipDTO;
    }

    @Transactional
    public boolean deleteByRelationshipId(long relationshipId) {
        QRelationship qRelationship = QRelationship.relationship1;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qRelationship.id.eq(relationshipId));
        Relationship relationship;
        queryFactory.select();
        relationship = queryFactory
                .select(qRelationship)
                .from(qRelationship)
                .where(booleanBuilder.getValue()).fetchOne();
        if (relationship == null)
            throw new VerificationException(ReplRyCode.COMPANY_NOT_DATA, ReplRyCode.COMPANY_NOT_DATA.getMessage());
        entityManager.remove(relationship);
//            entityManager.flush();
        entityManager.setFlushMode(FlushModeType.AUTO);

        return true;

    }

    public long relationshipCount(PageEnty<RelationshipListVO> relationshipListEntyVO) throws Exception {
        QRelationship qRelationship = QRelationship.relationship1;
        RelationshipListVO relationshipListVO = relationshipListEntyVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qRelationship.bindMain.eq(relationshipListVO.getParentId()));
        long count = queryFactory
                .select(qRelationship.count())
                .from(qRelationship)
                .where(booleanBuilder.getValue()).fetchCount();

        return count;
    }

    public List<RelationshipListDTO> pageRelationshipList(PageEnty<RelationshipListVO> relationshipListEntyVO) throws Exception {
        QRelationship qRelationship = QRelationship.relationship1;
        List<RelationshipListDTO> relationshipListDTOS = Lists.newArrayList();
        RelationshipListVO relationshipListVO = relationshipListEntyVO.getVo();
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qRelationship.bindMain.eq(relationshipListVO.getParentId()));
        List<Relationship> relationships = queryFactory
                .select(qRelationship)
                .from(qRelationship)
                .where(booleanBuilder.getValue())
                .offset((relationshipListEntyVO.getPage() - 1) * relationshipListEntyVO.getNum())
                .limit(relationshipListEntyVO.getNum())
                .orderBy(qRelationship.createTime.desc())
                .fetch();
        relationships.stream().forEach(rs -> {
            CompanyPersonal companyPersonal = companyPersonalService.findByPersona(rs.getBindSon());
            CompanyDTO companyDTO = companyService.findByCompanyId(companyPersonal.getCompanyId());
            CompanyClsDTO companyClsDTO = companyClsService.findByCompanyClsId(companyPersonal.getClsId());
            CompanyDepartmentDTO companyDepartmentDTO = companyDepartmentService.findByCompanyDepartmentId(companyClsDTO.getDepartmentId());
            RelationshipListDTO relationshipListDTO = new RelationshipListDTO();
            if (!StringUtils.isEmpty(companyDTO.getCompanyName()))
                relationshipListDTO.setSchoolName(companyDTO.getCompanyName());
            if (!StringUtils.isEmpty(companyDepartmentDTO.getGradeName()))
                relationshipListDTO.setDepartmentName(companyDepartmentDTO.getGradeName());
            if (!StringUtils.isEmpty(companyClsDTO.getClsName()))
                relationshipListDTO.setClsName(companyClsDTO.getClsName());
            relationshipListDTO.setPersonalName(companyPersonal.getPersonalName());
            relationshipListDTO.setNum(companyPersonal.getNum());
            relationshipListDTO.setRelationship(rs.getRelationship().name());
            relationshipListDTOS.add(relationshipListDTO);
        });


        return relationshipListDTOS;

    }


    public long relationshipCount(long bindMain, long bindSon) {
        QRelationship qRelationship = QRelationship.relationship1;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qRelationship.bindMain.eq(bindMain));
        booleanBuilder.and(qRelationship.bindSon.eq(bindSon));
        long relationship = queryFactory
                .select(qRelationship)
                .from(qRelationship)
                .where(booleanBuilder.getValue())
                .fetchCount();
        return relationship;
    }


    public Relationship existRelationship(long bindMain, long bindSon) {
        QRelationship qRelationship = QRelationship.relationship1;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        booleanBuilder.and(qRelationship.bindMain.eq(bindMain));
        booleanBuilder.and(qRelationship.bindSon.eq(bindSon));
        Relationship relationship = queryFactory
                .select(qRelationship)
                .from(qRelationship)
                .where(booleanBuilder.getValue())
                .fetchOne();
        return relationship;
    }

    public List<Relationship> relationshipsList(long bindMain, long bindSon) {
        QRelationship qRelationship = QRelationship.relationship1;
        BooleanBuilder booleanBuilder = new BooleanBuilder();
        if (bindMain != 0)
            booleanBuilder.and(qRelationship.bindMain.eq(bindMain));
        if (bindSon != 0)
            booleanBuilder.and(qRelationship.bindSon.eq(bindSon));
        List<Relationship> relationships = queryFactory
                .select(qRelationship)
                .from(qRelationship)
                .where(booleanBuilder.getValue())
                .fetch();
        return relationships;
    }

}
